﻿// Decompiled with JetBrains decompiler
// Type: TaleWorlds.CampaignSystem.PlayerCaptivity
// Assembly: TaleWorlds.CampaignSystem, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: E85F8C15-4DF6-4E9C-A58A-29177E40D07A
// Assembly location: D:\steam\steamapps\common\Mount & Blade II Bannerlord\bin\Win64_Shipping_Client\TaleWorlds.CampaignSystem.dll

using System.Collections.Generic;
using TaleWorlds.CampaignSystem.Actions;
using TaleWorlds.CampaignSystem.CampaignBehaviors;
using TaleWorlds.CampaignSystem.CharacterDevelopment;
using TaleWorlds.CampaignSystem.Encounters;
using TaleWorlds.CampaignSystem.GameMenus;
using TaleWorlds.CampaignSystem.GameState;
using TaleWorlds.CampaignSystem.Party;
using TaleWorlds.Core;
using TaleWorlds.SaveSystem;

#nullable disable
namespace TaleWorlds.CampaignSystem
{
  public class PlayerCaptivity
  {
    [SaveableField(0)]
    private CampaignTime _captivityStartTime;
    [SaveableField(1)]
    private PartyBase _captorParty;
    [SaveableField(2)]
    public int CountOfOffers;
    [SaveableField(3)]
    public int CurrentRansomAmount;
    private ICaptivityCampaignBehavior _captivityCampaignBehavior;
    [SaveableField(4)]
    private float _randomNumber;
    [SaveableField(5)]
    private CampaignTime _lastCheckTime;

    internal static void AutoGeneratedStaticCollectObjectsPlayerCaptivity(
      object o,
      List<object> collectedObjects)
    {
      ((PlayerCaptivity) o).AutoGeneratedInstanceCollectObjects(collectedObjects);
    }

    protected virtual void AutoGeneratedInstanceCollectObjects(List<object> collectedObjects)
    {
      CampaignTime.AutoGeneratedStaticCollectObjectsCampaignTime((object) this._captivityStartTime, collectedObjects);
      collectedObjects.Add((object) this._captorParty);
      CampaignTime.AutoGeneratedStaticCollectObjectsCampaignTime((object) this._lastCheckTime, collectedObjects);
    }

    internal static object AutoGeneratedGetMemberValueCountOfOffers(object o)
    {
      return (object) ((PlayerCaptivity) o).CountOfOffers;
    }

    internal static object AutoGeneratedGetMemberValueCurrentRansomAmount(object o)
    {
      return (object) ((PlayerCaptivity) o).CurrentRansomAmount;
    }

    internal static object AutoGeneratedGetMemberValue_captivityStartTime(object o)
    {
      return (object) ((PlayerCaptivity) o)._captivityStartTime;
    }

    internal static object AutoGeneratedGetMemberValue_captorParty(object o)
    {
      return (object) ((PlayerCaptivity) o)._captorParty;
    }

    internal static object AutoGeneratedGetMemberValue_randomNumber(object o)
    {
      return (object) ((PlayerCaptivity) o)._randomNumber;
    }

    internal static object AutoGeneratedGetMemberValue_lastCheckTime(object o)
    {
      return (object) ((PlayerCaptivity) o)._lastCheckTime;
    }

    public static PartyBase CaptorParty
    {
      get => Campaign.Current.PlayerCaptivity._captorParty;
      set
      {
        if (value != null)
          Campaign.Current.PlayerCaptivity._captorParty.PrisonRoster.RemoveTroop(Hero.MainHero.CharacterObject);
        Campaign.Current.PlayerCaptivity._captorParty = value;
        if (value == null)
          return;
        Campaign.Current.PlayerCaptivity._captorParty.AddPrisoner(Hero.MainHero.CharacterObject, 1);
        if ((Game.Current.GameStateManager.ActiveState as MapState).AtMenu)
          GameMenu.SwitchToMenu(PlayerCaptivity.CaptorParty.IsSettlement ? "settlement_wait" : "prisoner_wait");
        else
          GameMenu.ActivateGameMenu(PlayerCaptivity.CaptorParty.IsSettlement ? "settlement_wait" : "prisoner_wait");
      }
    }

    private ICaptivityCampaignBehavior CaptivityCampaignBehavior
    {
      get
      {
        if (this._captivityCampaignBehavior == null)
          this._captivityCampaignBehavior = Campaign.Current.GetCampaignBehavior<ICaptivityCampaignBehavior>();
        return this._captivityCampaignBehavior;
      }
    }

    public static float RandomNumber
    {
      get => Campaign.Current.PlayerCaptivity._randomNumber;
      set => Campaign.Current.PlayerCaptivity._randomNumber = value;
    }

    public static bool IsCaptive => Campaign.Current.PlayerCaptivity._captorParty != null;

    public static int CaptiveTimeInDays
    {
      get => (int) (CampaignTime.Now - PlayerCaptivity.CaptivityStartTime).ToDays;
    }

    public static CampaignTime CaptivityStartTime
    {
      get => Campaign.Current.PlayerCaptivity._captivityStartTime;
    }

    public static CampaignTime LastCheckTime
    {
      get => Campaign.Current.PlayerCaptivity._lastCheckTime;
      set => Campaign.Current.PlayerCaptivity._lastCheckTime = value;
    }

    public static void StartCaptivity(PartyBase captorParty)
    {
      Campaign.Current.PlayerCaptivity.StartCaptivityInternal(captorParty);
      PlayerCaptivity.RandomNumber = MBRandom.RandomFloat;
    }

    public static void OnPlayerCharacterChanged()
    {
      if (!Hero.MainHero.IsPrisoner)
        return;
      Campaign.Current.PlayerCaptivity.StartCaptivityInternal(Hero.MainHero.PartyBelongedToAsPrisoner);
      PlayerCaptivity.RandomNumber = MBRandom.RandomFloat;
      PlayerCaptivity.CaptorParty = Hero.MainHero.PartyBelongedToAsPrisoner;
    }

    public void SetRansomAmount() => this.CurrentRansomAmount = this.GetPlayerRansomValue();

    private int GetPlayerRansomValue()
    {
      return (int) (((double) MBRandom.RandomFloat * 0.5 + 0.5) * ((double) Hero.MainHero.Gold * 0.05000000074505806 + 300.0) * (Hero.MainHero.PartyBelongedToAsPrisoner.IsSettlement ? (Hero.MainHero.PartyBelongedToAsPrisoner.Settlement.MapFaction.IsKingdomFaction ? 4.0 : 2.0) : 1.0) * (!Hero.MainHero.PartyBelongedToAsPrisoner.IsMobile || !Hero.MainHero.PartyBelongedToAsPrisoner.MobileParty.IsLordParty ? 1.0 : 2.0) * (Hero.MainHero.GetPerkValue(DefaultPerks.Trade.ManOfMeans) ? 1.0 + (double) DefaultPerks.Trade.ManOfMeans.SecondaryBonus : 1.0));
    }

    private void StartCaptivityInternal(PartyBase captorParty)
    {
      this._captivityStartTime = CampaignTime.Now;
      this._lastCheckTime = CampaignTime.Now;
      if (PlayerEncounter.Current != null)
        PlayerEncounter.LeaveEncounter = true;
      if (MobileParty.MainParty.CurrentSettlement != null)
        LeaveSettlementAction.ApplyForParty(MobileParty.MainParty);
      MobileParty.MainParty.IsActive = false;
      PartyBase.MainParty.UpdateVisibilityAndInspected();
      this._captorParty = captorParty;
      this._captorParty.SetAsCameraFollowParty();
      this._captorParty.UpdateVisibilityAndInspected();
      if (MobileParty.MainParty.Army == null)
        return;
      if (MobileParty.MainParty.Army.LeaderParty == MobileParty.MainParty)
        DisbandArmyAction.ApplyByPlayerTakenPrisoner(MobileParty.MainParty.Army);
      MobileParty.MainParty.Army = (Army) null;
    }

    private void EndCaptivityInternal()
    {
      if (Hero.MainHero.IsAlive)
      {
        PartyBase.MainParty.AddElementToMemberRoster(CharacterObject.PlayerCharacter, 1, true);
        MobileParty.MainParty.ChangePartyLeader(Hero.MainHero);
      }
      if (Hero.MainHero.CurrentSettlement != null)
      {
        if (PlayerEncounter.Current != null)
          PlayerEncounter.LeaveSettlement();
        else if (Hero.MainHero.IsAlive)
          LeaveSettlementAction.ApplyForParty(MobileParty.MainParty);
        else
          LeaveSettlementAction.ApplyForCharacterOnly(Hero.MainHero);
      }
      if (PlayerEncounter.Current != null)
        PlayerEncounter.Finish();
      else if (Campaign.Current.CurrentMenuContext != null)
        GameMenu.ExitToLast();
      if (this._captorParty.IsActive)
        this._captorParty.PrisonRoster.RemoveTroop(Hero.MainHero.CharacterObject);
      if (Hero.MainHero.IsAlive)
        Hero.MainHero.ChangeState(Hero.CharacterStates.Active);
      if (Hero.MainHero.IsAlive)
      {
        MobileParty.MainParty.IsActive = true;
        PartyBase.MainParty.SetAsCameraFollowParty();
        MobileParty.MainParty.Ai.SetMoveModeHold();
        SkillLevelingManager.OnMainHeroReleasedFromCaptivity(PlayerCaptivity.CaptivityStartTime.ElapsedHoursUntilNow);
        PartyBase.MainParty.UpdateVisibilityAndInspected();
      }
      CampaignEventDispatcher.Instance.OnHeroPrisonerReleased(Hero.MainHero, this._captorParty, this._captorParty.MapFaction, EndCaptivityDetail.ReleasedAfterEscape);
      this._captorParty = (PartyBase) null;
      this.CountOfOffers = 0;
      this.CurrentRansomAmount = 0;
    }

    public static void EndCaptivity()
    {
      if (Hero.MainHero.IsAlive)
      {
        if (Hero.MainHero.IsWounded)
          Hero.MainHero.HitPoints = 20;
        if (Hero.MainHero.PartyBelongedToAsPrisoner != null && Hero.MainHero.PartyBelongedToAsPrisoner.IsMobile)
          Hero.MainHero.PartyBelongedToAsPrisoner.MobileParty.Ai.SetDoNotAttackMainParty(12);
        PlayerEncounter.ProtectPlayerSide(4f);
      }
      Campaign.Current.PlayerCaptivity.EndCaptivityInternal();
    }

    internal void Update(float dt)
    {
      MapState activeState = Game.Current.GameStateManager.ActiveState as MapState;
      if (!PlayerCaptivity.IsCaptive || (double) dt <= 0.0 && (activeState == null || activeState.AtMenu))
        return;
      if (this._captorParty.IsMobile && this._captorParty.MobileParty.IsActive)
        PartyBase.MainParty.MobileParty.Position2D = this._captorParty.MobileParty.Position2D;
      else if (this._captorParty.IsSettlement)
        PartyBase.MainParty.MobileParty.Position2D = this._captorParty.Settlement.GatePosition;
      if (activeState != null && !activeState.AtMenu)
        GameMenu.ActivateGameMenu(PlayerCaptivity.CaptorParty.IsSettlement ? "settlement_wait" : "prisoner_wait");
      if (!PlayerCaptivity.IsCaptive)
        return;
      this.CaptivityCampaignBehavior?.CheckCaptivityChange(dt);
    }
  }
}
